﻿using System;
using System.Buffers;
using System.Runtime.CompilerServices;

namespace eNets.IO.Binary;

static class ReadOnlySequenceExtensions
{
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool TryPositionOf<T>(in this ReadOnlySequence<T> source, T value, out SequencePosition position)
        where T : IEquatable<T>
    {
        if (!source.IsSingleSegment)
            return TryPositionOfMultiSegment<T>(source, value, out position);
        int num = source.First.Span.IndexOf<T>(value);
        if (num != -1)
        {
            position = source.GetPosition((long)num);
            return true;
        }

        position = default;
        return false;
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private static bool TryPositionOfMultiSegment<T>(in ReadOnlySequence<T> source, T value, out SequencePosition position)
        where T : IEquatable<T>
    {
        SequencePosition start = source.Start;
        SequencePosition origin = start;
        ReadOnlyMemory<T> memory;
        while (source.TryGet(ref start, out memory, true))
        {
            int num = memory.Span.IndexOf<T>(value);
            if (num != -1)
            {
                position = source.GetPosition((long)num, origin);
                return true;
            }
            if (start.GetObject() != null)
                origin = start;
            else
                break;
        }

        position = default;
        return false;
    }
}